
#pragma once
#include <iostream>
#include <pthread.h>
#include <string>
#include <functional>


namespace ThreadMoudle
{

    enum class TSTAUS
    {
        THREAD_NEW,
        THREAD_RUNNING,
        THREAD_STOP
    };
    int cnt = 0;

    template <typename B>
    using task = std::function<void(B)>;

    template <typename T>

    class Thread
    {
    public:
        static void *run(void *obj)
        {
            Thread *self = static_cast<Thread *>(obj);

            pthread_setname_np(pthread_self(), self->_name.c_str());

            self->style = TSTAUS::THREAD_RUNNING;
            self->_func(self->GteData());
            if (!self->_joined)
            {
                pthread_detach(pthread_self());
            }
            return nullptr;
        }

        void SetName()
        {
            _name ="Thread-" + _name+": ";
        }

        // 线程默认为joinable
        Thread(task<T> my_func,T td) :_data(td), _name(name),_func(my_func), _joined(true), style(TSTAUS::THREAD_NEW)
        {
            SetName();
        }

        void EnableDeath()
        {
            if (style == TSTAUS::THREAD_NEW)
            {
                _joined = false;
            }
        }

        void EnableJoined()
        {
            if (style == TSTAUS::THREAD_NEW)
            {
                _joined = true;
            }
        }

        bool Start()
        {
            if (style == TSTAUS::THREAD_RUNNING)
            {
                return true;
            }
            int n = pthread_create(&_td, nullptr, run, nullptr);
            if (n != 0)
                return false;
            return true;
        }

        bool Join()
        {
            if (_joined)
            {
                int n = pthread_join(_td, nullptr);
                if (n == 0)
                {
                    return true;
                }
                return false;
            }
            false;
        }

        T& GteData()
        {
            return _data;
        }
        ~Thread()
        {
            
        }

        std::string name() {
            return _name;
        }

    private:
        pthread_t _td;
        std::string _name;

        T _data;
        bool _joined;
        task<T> _func;
        TSTAUS style;
    };

}